package concurrent.mycondition.CSmodel;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 存储 生产者消息的通道
 *
 * Condition的await方法和lock#unlock()一样释放锁
 */
public class MiddlewareChannel {
    public int init_capacity = 0;//初始存储
    public static int max_capacity = 6;//最大存储 最大容量值

    private final Lock lock = new ReentrantLock();
    private final Condition consumer = lock.newCondition();
    private final Condition producer = lock.newCondition();

    /**
     * 消息端产生消息
     */
    public void send() {
        //拿到锁
        try {
            lock.lock();
            //判断通道是否已满，如果已满
            if(init_capacity > max_capacity) {
                try {
                    System.out.println("库存已满,生产者等待发送信息...");
                    //生产者  等待发送消息
                    producer.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                //通知消费者 消费消息
                System.out.println(Thread.currentThread().getName()+":生产消息" +"库存容量:"+(++init_capacity));
                //唤醒所有消费者，获得锁只要不调用await方法，就不会释放锁，，
                // 不满足条件就不会被唤醒，就算unlock释放了锁，producer也获取不到锁，执行的条件就是释放锁
                // signal应该会唤醒等待的consumer才对，不知为何没有唤醒
                consumer.signalAll();
            }

        } catch (Exception e1) {
            e1.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 消息端 消费消息
     */
    public void accept() {

        try {
            lock.lock();

            //判断通道是否有消息
            if (init_capacity > 0) {  //通道有消息
                //弹出消息
                System.out.println(Thread.currentThread().getName()+":消费消息:"+" 库存容量:"+(--init_capacity));
                //消费完唤醒生产者，让生产者去生产消息
                producer.signalAll();
            }else {           //通道无消息
                try {
                    System.out.println("库存不足,等待生产者生产消息...");
                    //等待消费，await会使当前线程释放锁，然后进入等待队列，等待被唤醒
                    consumer.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        } catch (Exception e1) {
            e1.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

}